﻿// CheckProjectTreeCtrl.cpp: 实现文件
//

#include "stdafx.h"
#include "zChecker.h"
#include "CheckProjectTreeCtrl.h"

#include "MainFrm.h"
#include "CheckerDoc.h"
#include "CheckerView.h"


//#include "LandsatMetaDialog.h"

// CCheckProjectTreeCtrl

IMPLEMENT_DYNAMIC(CCheckProjectTreeCtrl, zxCheckProjectTreeCtrl)

CCheckProjectTreeCtrl::CCheckProjectTreeCtrl()
{

}

CCheckProjectTreeCtrl::~CCheckProjectTreeCtrl()
{
}


BEGIN_MESSAGE_MAP(CCheckProjectTreeCtrl, zxCheckProjectTreeCtrl)
	ON_NOTIFY_REFLECT(NM_RCLICK, &CCheckProjectTreeCtrl::OnNMRClick)
	ON_WM_CREATE()
	ON_COMMAND(ID_RMENU_PROJECT_PROPERTY, &CCheckProjectTreeCtrl::OnRmenuProjectProperty)
	ON_COMMAND(ID_RMENU_PROJECT_CASE, &CCheckProjectTreeCtrl::OnRmenuProjectCase)
	ON_COMMAND(ID_RMENU_PROJECT_DATASOURCE_PROPERTY, &CCheckProjectTreeCtrl::OnRmenuProjectDatasourceProperty)
	ON_COMMAND(ID_RMENU_PROJECT_DATASOURCE_REMOVE, &CCheckProjectTreeCtrl::OnRmenuRemoveDataSource)
	ON_COMMAND(IDR_RMENU_PROJECT_DATASET_PROPERTY, &CCheckProjectTreeCtrl::OnRmenuProjectDatasetProperty)
	ON_COMMAND(IDR_RMENU_PROJECT_DATASET_REMOVE, &CCheckProjectTreeCtrl::OnRmenuProjectDatasetRemove)
	ON_COMMAND(IDR_RMENU_PROJECT_DATASET_CHECK_METADATA, &CCheckProjectTreeCtrl::OnRmenuProjectDatasetCheckMetadata)
	ON_COMMAND(IDR_RMENU_PROJECT_DATASET_ADD_TO_MAP, &CCheckProjectTreeCtrl::OnRmenuProjectDatasetAddToMap)

	ON_COMMAND(ID_RMENU_PROJECT_CHECK_RESULT_EXPORT, &CCheckProjectTreeCtrl::OnRmenuProjectCheckResultExport)
END_MESSAGE_MAP()



// CCheckProjectTreeCtrl 消息处理程序

int CCheckProjectTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (zxCheckProjectTreeCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码

	return 0;
}



void CCheckProjectTreeCtrl::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;

	if (!m_pProject)
	{
		return;
	}

	CPoint pt, spt;
	if (!GetCursorPos(&pt))
	{
		return;
	}
	spt = pt;
	ScreenToClient(&pt);
	UINT uFlag = 0;
	HTREEITEM hItem = HitTest(pt, &uFlag);
	if ((NULL == hItem) || !(TVHT_ONITEM&uFlag))
	{
		return;
	}
	SelectItem(hItem);
	m_hSelected = hItem;

	int nMenuID = -1;
	int nType = GetNodeType(hItem);
	switch (nType)
	{
	case PROJECT_TREE_ROOT_NODE:
		nMenuID = IDR_RMENU_PROJECT;
		break;
	case PROJECT_TREE_CASE_ROOT_NODE:
		break;
	case PROJECT_TREE_CASE_NODE:
		break;
	case PROJECT_TREE_SOURCE_ROOT_NODE:
		break;
	case PROJECT_TREE_SOURCE_NODE:
	{
		ck::DataSource* pDataSource = (ck::DataSource*)GetItemData(hItem);
		if (pDataSource)
		{
			ck::ckDataSourceType type = pDataSource->GetType();
			switch (type)
			{
			case ck::ckFileDataSource:
				nMenuID = IDR_RMENU_PROJECT_DATASET;
				break;
			default:
				nMenuID = IDR_RMENU_PROJECT_DATASOURCE;
				break;
			}
		}
	}
	break;
	case PROJECT_TREE_DATASET_NODE:
		//弹出数据集右键菜单
		nMenuID = IDR_RMENU_PROJECT_DATASET;
		break;
	}

	if (nMenuID > 0)
	{
		CMenu m, *mn;
		m.LoadMenu(nMenuID);//加载菜单资源
		mn = m.GetSubMenu(0);//获取菜单子项
		CMenu* pSubMenu = mn->GetSubMenu(0);
		mn->TrackPopupMenu(TPM_LEFTALIGN, spt.x, spt.y, this);    //显示菜单
	}

}

/************************************************************************/
/* 显示工程属性对话框                                                     */
/************************************************************************/
void CCheckProjectTreeCtrl::OnRmenuProjectProperty()
{
	// TODO: 在此添加命令处理程序代码
	if (!m_pProject)
	{
		AfxMessageBox("检查工程尚未打开");
		return;
	}

	//CCheckProjectPropertyDialog dlg;
	zxCheckProjectPropertyDialog dlg;
	dlg.SetProject(m_pProject);
	dlg.DoModal();

}

/************************************************************************/
/* 显示工程方案对话框                                                     */
/************************************************************************/
void CCheckProjectTreeCtrl::OnRmenuProjectCase()
{
	// TODO: 在此添加命令处理程序代码
	AfxMessageBox("OnRmenuProjectCase");
}

void CCheckProjectTreeCtrl::OnRmenuProjectDatasourceProperty()
{
	// TODO: 在此添加命令处理程序代码

}


/************************************************************************/
/* 从工程上删除数据集                                                     */
/************************************************************************/
void CCheckProjectTreeCtrl::OnRmenuRemoveDataSource()
{
	// TODO: 在此添加命令处理程序代码
	if (m_hSelected != NULL)
	{
		RESULTCODE rc;
		ck::DataSource* pDataSource = (ck::DataSource*)GetItemData(m_hSelected);
		ck::ckDataSourceType type = pDataSource->GetType();
		switch (type)
		{
		case ck::ckFileDataSource:
		{
			const char* szName = pDataSource->GetName();
			z_uint32 nProjCode = m_pProject->GetCode();
			//z_uint32 nSourceCode = pDataSource->GetCode();

			ck::CheckProjectManager* pProjectManager = NULL;
			pProjectManager = ck::CheckProjectManager::GetInstance();
			pProjectManager->RemoveDataSource(nProjCode, pDataSource->GetName());
			rc = m_pProject->RemoveDataSource(szName);

			RemoveDataSourceNode(m_hSelected);
			m_hSelected = NULL;
		}
		break;
		case ck::ckFolderDataSource:
		{
			RemoveDataSourceNode(m_hSelected);
			m_hSelected = NULL;

			const char* szSourceName = pDataSource->GetName();
			z_uint32 nSourceCode = pDataSource->GetCode();
			z_uint32 nProjCode = m_pProject->GetCode();
			//z_uint32 nSourceCode = pDataSource->GetCode();

			//ck::CheckProjectManager* pProjectManager = NULL;
			//pProjectManager = ck::CheckProjectManager::GetInstance();
			//pProjectManager->RemoveDataSource(nProjCode, pDataSource->GetName());

			ck::DataSourceManager* pSourceManager = ck::DataSourceManager::GetInstance();
			pSourceManager->RemoveDatasets(nSourceCode);
			pSourceManager->RemoveDataSource(nProjCode, szSourceName);

			rc = m_pProject->RemoveDataSource(szSourceName);

		}
		break;
		case ck::ckGDBDataSource:
			break;
		default:
			break;
		}

	}
}

/************************************************************************/
/* 显示工程-数据集属性-对话框                                             */
/************************************************************************/
void CCheckProjectTreeCtrl::OnRmenuProjectDatasetProperty()
{
	// TODO: 在此添加命令处理程序代码
	//AfxMessageBox("OnRmenuProjectDatasetProperty");

	HTREEITEM hItem = GetSelectedItem();
	if (!hItem)
	{
		return;
	}

	//获取Dataset指针
	ck::data::Dataset* pDataset = NULL;

	int nMenuID = -1;
	int nType = GetNodeType(hItem);
	switch (nType)
	{
	case PROJECT_TREE_SOURCE_NODE:
	{
		//说明这是文件类型的Dataset，GetItemData获取到的是DataSource
		//因为文件类型的Dataset和DataSource共享相同的Tree节点
		ck::DataSource* pDataSource = (ck::DataSource*)GetItemData(hItem);
		if (pDataSource)
		{
			ck::ckDataSourceType type = pDataSource->GetType();
			switch (type)
			{
			case ck::ckFileDataSource:
			{
				ck::FileDataSource* pFileDataSource = static_cast<ck::FileDataSource*>(pDataSource);
				pDataset = pFileDataSource->GetDataset(m_pProject->GetProductType());
			}
			break;
			}
		}
	}
	break;
	case PROJECT_TREE_DATASET_NODE:
	{
		//真正的Dataset节点
		pDataset = (ck::data::Dataset*)GetItemData(hItem);
		if (pDataset)
		{
			//由于文件类型的Dataset最后要释放，所以这里对pDataset的引用计数增加1
			pDataset->AddRef();
		}
		break;
	}
	}

	//显示对话框
	if (pDataset == NULL)
	{
		return;
	}

	ck::ckDataProductType prudType = m_pProject->GetProductType();
	switch (prudType)
	{
	case ck::ckDptUnknown:
		break;
	case ck::ckDptLandCover30:
		break;
	case ck::ckDptLandCover10:
		break;
	case ck::ckDptLandsat05:
	case ck::ckDptLandsat08:
	{
		/* 显示Landsat元数据对话框 */
		ck::data::Landsat* pLandsat = (ck::data::Landsat*)pDataset;
		zxLandsatMetaDialog dlg;
		dlg.SetDataset(pLandsat);
		dlg.DoModal();
	}
	break;
	}

	pDataset->Release();
}



/************************************************************************/
/* 从检查工程中删除数据集                                                 */
/************************************************************************/
void CCheckProjectTreeCtrl::OnRmenuProjectDatasetRemove()
{
	// TODO: 在此添加命令处理程序代码
	HTREEITEM hItem = GetSelectedItem();
	if (!hItem)
	{
		return;
	}

	int nNodeType = GetNodeType(hItem);
	switch (nNodeType)
	{
	case PROJECT_TREE_SOURCE_NODE:
	{	//文件型数据集的Dataset节点和DataSource是同一个
		z_uint32 nSourceCode = 0;
		ck::DataSource* pSource = NULL;
		ck::DataSourceManager* pSourceManager = ck::DataSourceManager::GetInstance();

		pSource = (ck::DataSource*)(GetItemData(hItem));
		CString strSourceName = GetItemText(hItem);

		pSourceManager->RemoveDataSource(m_pProject->GetCode(), strSourceName);
		m_pProject->RemoveDataSource(strSourceName);

		RemoveDataSourceNode(hItem);
	}
	break;
	case PROJECT_TREE_DATASET_NODE:
	{
		ck::data::Dataset* pDataset = NULL;
		pDataset = (ck::data::Dataset*)GetItemData(hItem);
		if (pDataset)
		{
			HTREEITEM hSourceItem = GetParentItem(hItem);

			ck::DataSource* pDataSource = (ck::DataSource*)GetItemData(hSourceItem);
			ck::ckDataSourceType type = pDataSource->GetType();

			switch (type)
			{
			case ck::ckFolderDataSource:
			{
				ck::FolderDataSource* pFolderSource = (ck::FolderDataSource*)pDataSource;
				pFolderSource->RemoveDataset(pDataset->GetName());
				RemoveDatasetNode(hItem, pDataset);

			}
			break;

			}
		}
	}
	break;
	}
}

/************************************************************************/
/* Dataset的元数据检查                                                   */
/************************************************************************/
void CCheckProjectTreeCtrl::OnRmenuProjectDatasetCheckMetadata()
{
	// TODO: 在此添加命令处理程序代码

	HTREEITEM hItem = GetSelectedItem();
	if (!hItem)
	{
		return;
	}

	//获取Dataset指针
	ck::data::Dataset* pDataset = NULL;

	int nMenuID = -1;
	int nType = GetNodeType(hItem);
	switch (nType)
	{
	case PROJECT_TREE_SOURCE_NODE:
	{
		//说明这是文件类型的Dataset，GetItemData获取到的是DataSource
		//因为文件类型的Dataset和DataSource共享相同的Tree节点
		ck::DataSource* pDataSource = (ck::DataSource*)GetItemData(hItem);
		if (pDataSource)
		{
			ck::ckDataSourceType type = pDataSource->GetType();
			switch (type)
			{
			case ck::ckFileDataSource:
			{
				ck::FileDataSource* pFileDataSource = static_cast<ck::FileDataSource*>(pDataSource);
				pDataset = pFileDataSource->GetDataset(m_pProject->GetProductType());
			}
			break;
			}
		}
	}
	break;
	case PROJECT_TREE_DATASET_NODE:
	{
		//真正的Dataset节点
		pDataset = (ck::data::Dataset*)GetItemData(hItem);
		if (pDataset)
		{
			//由于文件类型的Dataset最后要释放，所以这里对pDataset的引用计数增加1
			pDataset->AddRef();
		}
		break;
	}
	}

	//显示对话框
	if (pDataset == NULL)
	{
		return;
	}

	ck::ckDataProductType prudType = m_pProject->GetProductType();
	switch (prudType)
	{
	case ck::ckDptUnknown:
		break;
	case ck::ckDptLandCover30:
		break;
	case ck::ckDptLandCover10:
		break;
	case ck::ckDptLandsat05:
	case ck::ckDptLandsat08:
	{
		if (!pDataset->IsOpen())
		{
			pDataset->Open();
		}
		if (pDataset->IsOpen())
		{
			//检查Landsat元数据
			ck::data::Landsat* pLandsat = (ck::data::Landsat*)pDataset;
			ck::check::CheckResult* rst = NULL;
			ck::check::CheckResultSet reset;

			//元数据完整性检查
			ck::check::LandsatMetaIntegrityChecker intChecker;
			intChecker.SetDataset(pLandsat);
			intChecker.Check();
			rst = intChecker.GetResult();
			if (rst)	reset.Add(rst);

			//元数据正确性检查
			ck::check::LandsatMetaCorrectnessChecker crtChecker;
			crtChecker.SetDataset(pLandsat);
			crtChecker.Check();
			rst = crtChecker.GetResult();
			if (rst)	reset.Add(rst);

			//元数据文件完整性检查
			ck::check::LandsatFileChecker fileChecker;
			fileChecker.SetDataset(pLandsat);
			fileChecker.Check();
			rst = fileChecker.GetResult();
			if (rst)	reset.Add(rst);

			CMainFrame* pFrmMain = (CMainFrame*)AfxGetMainWnd();
			pFrmMain->m_wndOutput.PopulateCheckResult(&reset);

			AfxMessageBox("元数据检查完成");
		}
	}
	break;
	}

	pDataset->Release();
}

void CCheckProjectTreeCtrl::OnRmenuProjectDatasetAddToMap()
{
	// TODO: 在此添加命令处理程序代码
	HTREEITEM hItem = GetSelectedItem();
	if (!hItem)
	{
		return;
	}

	//获取Dataset指针
	ck::data::Dataset* pDataset = NULL;

	int nMenuID = -1;
	int nType = GetNodeType(hItem);
	switch (nType)
	{
	case PROJECT_TREE_SOURCE_NODE:
	{
		//说明这是文件类型的Dataset，GetItemData获取到的是DataSource
		//因为文件类型的Dataset和DataSource共享相同的Tree节点
		ck::DataSource* pDataSource = (ck::DataSource*)GetItemData(hItem);
		if (pDataSource)
		{
			ck::ckDataSourceType type = pDataSource->GetType();
			switch (type)
			{
			case ck::ckFileDataSource:
			{
				ck::FileDataSource* pFileDataSource = static_cast<ck::FileDataSource*>(pDataSource);
				pDataset = pFileDataSource->GetDataset(m_pProject->GetProductType());
			}
			break;
			}
		}
	}
	break;
	case PROJECT_TREE_DATASET_NODE:
	{
		//真正的Dataset节点
		pDataset = (ck::data::Dataset*)GetItemData(hItem);
		if (pDataset)
		{
			//由于文件类型的Dataset最后要释放，所以这里对pDataset的引用计数增加1
			pDataset->AddRef();
		}
		break;
	}
	}

	//显示对话框
	if (pDataset == NULL)
	{
		return;
	}

	ck::ckDataProductType prudType = m_pProject->GetProductType();
	switch (prudType)
	{
	case ck::ckDptUnknown:
		break;
	case ck::ckDptLandCover30:
		break;
	case ck::ckDptLandCover10:
		break;
	case ck::ckDptLandsat05:
	case ck::ckDptLandsat08:
	{
		switch(nType)
		{
		case PROJECT_TREE_SOURCE_NODE:
		{
			ck::data::Landsat* pLandsat = (ck::data::Landsat*)pDataset;
			const char* szPath = pLandsat->GetPath();
			AddLandsatToMap(szPath);

			//ck::data::RasterDataset* pRasterDataset = (ck::data::RasterDataset*)pDataset;
			//const char* szPath = pRasterDataset->GetPath();
			//AddTifToMap(szPath);
		}
			break;
		case PROJECT_TREE_DATASET_NODE:
		{
			//ck::data::RasterDataset* pRasterDataset = (ck::data::RasterDataset*)pDataset;
			//const char* szPath = pRasterDataset->GetPath();
			//AddTifToMap(szPath);
		}
		
			break;
		}
	}
	break;
	}

	pDataset->Release();
}

/************************************************************************/
/* 导出检查结果                                                          */
/************************************************************************/
void CCheckProjectTreeCtrl::OnRmenuProjectCheckResultExport()
{
	// TODO: 在此添加命令处理程序代码
	ck::check::CheckResultSet* pResultSet = m_pProject->GetCheckResultSet();
	if (pResultSet == NULL)
	{
		AfxMessageBox("尚未执行检查");
		return;
	}

	ck::check::CheckResultWriter* pWriter = new ck::check::XMLCheckResultWriter();
	pWriter->Write(pResultSet, "G:\\Temp\\chk\\cresult.xml");
	pWriter->Release();
	
}

void CCheckProjectTreeCtrl::AddLandsatToMap(const char* szLansatPath)
{
	IGroupLayerPtr	pGroupLayer = OpenLayerLandsat5(szLansatPath);
	if (pGroupLayer != NULL)
	{
		CheckerView* pView = (CheckerView*)(((CMainFrame*)AfxGetMainWnd())->GetActiveView());
		pView->AddLayer(pGroupLayer);
		pView->RefreshMap();
	}


}

void CCheckProjectTreeCtrl::AddTifToMap(const char* szTifPath)
{
	IRasterLayerPtr pRasterLayer = OpenLayerTif(szTifPath);
	if (pRasterLayer)
	{
		ILayerPtr pLayer(pRasterLayer);

		CheckerView* pView = (CheckerView*)(((CMainFrame*)AfxGetMainWnd())->GetActiveView());
		pView->AddLayer(pLayer);
		pView->RefreshMap();
	}
}

IGroupLayerPtr CCheckProjectTreeCtrl::OpenLayerLandsat5(const char* szPath)
{
	char szFolderName[_MAX_FNAME];
	memset(szFolderName, 0, _MAX_FNAME);
	_splitpath(szPath, NULL, NULL, szFolderName, NULL);

	IGroupLayerPtr pGroupLayer(CLSID_GroupLayer);
	pGroupLayer->put_Name((CComBSTR)szFolderName);

	//遍历文件夹，添加各个波段
	char szExt[_MAX_EXT];
	char szFilter[_MAX_PATH];
	_makepath(szFilter, NULL, szPath, "*", "*");
	CFileFind finder;
	BOOL ret = finder.FindFile(szFilter);
	while (ret)
	{
		ret = finder.FindNextFile();
		if (ret)
		{
			if ((!finder.IsDirectory()) && (!finder.IsDots()))
			{
				CString strPath = finder.GetFilePath();
				_splitpath(strPath, NULL, NULL, NULL, szExt);
				if (_stricmp(szExt, ".TIF") == 0)
				{
					IRasterLayerPtr pRasterLayer = OpenLayerTif(strPath);
					pRasterLayer->put_Visible(VARIANT_FALSE);
					pGroupLayer->Add(pRasterLayer);
				}
			}
		}
	}
	finder.Close();

	return pGroupLayer;
}


IRasterLayerPtr CCheckProjectTreeCtrl::OpenLayerTif(CString strPath)
{
	char szDrv[_MAX_DRIVE];
	char szDir[_MAX_DIR];
	char szName[_MAX_FNAME];
	char szExt[_MAX_EXT];

	char szFPath[_MAX_PATH];
	char szFName[_MAX_FNAME];

	_splitpath(strPath, szDrv, szDir, szName, szExt);
	_makepath(szFPath, szDrv, szDir, NULL, NULL);
	_makepath(szFName, NULL, NULL, szName, szExt);

	IWorkspaceFactoryPtr pWorksFactory;
	HRESULT hr = pWorksFactory.CreateInstance(CLSID_RasterWorkspaceFactory);
	if (FAILED(hr))
	{
		AfxMessageBox("Error");
		return NULL;
	}

	IWorkspacePtr pWorkspace;
	hr = pWorksFactory->OpenFromFile(CComBSTR(szFPath), 0, &pWorkspace);
	if (FAILED(hr))
	{
		AfxMessageBox("Error");
		return NULL;
	}

	IRasterWorkspacePtr pRasterWorkspace(pWorkspace);
	IRasterDatasetPtr pRasterDataset = NULL;
	hr = pRasterWorkspace->OpenRasterDataset(CComBSTR(szFName), &pRasterDataset);
	if (FAILED(hr))
	{
		AfxMessageBox("Error");
		return NULL;
	}

	IRasterLayerPtr pRasterLayer(CLSID_RasterLayer);
	hr = pRasterLayer->CreateFromDataset(pRasterDataset);
	if (FAILED(hr))
	{
		AfxMessageBox("Error");
		return NULL;
	}
	else
	{
		IRasterPtr pRaster = NULL;
		IRasterDataset2Ptr pRasterDataset2 = (IRasterDataset2Ptr)pRasterDataset;
		hr = pRasterDataset2->CreateFullRaster(&pRaster);
		if (FAILED(hr))
		{
			AfxMessageBox("Failed");
		}
		else
		{
			IRasterBandCollectionPtr pRasterBandCollection = (IRasterBandCollectionPtr)pRaster;
			IRasterBandPtr pRasterBand = NULL;
			hr = pRasterBandCollection->Item(0, &pRasterBand);
			if (SUCCEEDED(hr))
			{
				//NoDataValue
				IRasterPropsPtr pRasterProps = (IRasterPropsPtr)pRasterBand;
				VARIANT var1;
				pRasterProps->get_NoDataValue(&var1);
				unsigned short noDataValue = var1.uiVal;

				VARIANT_BOOL has;
				pRasterBand->HasStatistics(&has);
				if (has != VARIANT_TRUE)
				{
					pRasterBand->ComputeStatsAndHist();
				}
				IRasterHistogramPtr pHistogram = NULL;
				hr = pRasterBand->get_Histogram(&pHistogram);
				if (SUCCEEDED(hr))
				{
					if (pHistogram != NULL)
					{
						VARIANT val;
						pHistogram->get_Counts(&val);
						VARTYPE type = val.vt;
						if (type == (VT_ARRAY | VT_R8))
						{
							double *pData = NULL;
							SAFEARRAY* psa = val.parray;
							SafeArrayAccessData(psa, (void**)&pData);
							//psa->cbElements
							SafeArrayUnaccessData(psa);
						}
					}
				}

				IRasterStatisticsPtr pStatistics = NULL;
				hr = pRasterBand->get_Statistics(&pStatistics);
				if (SUCCEEDED(hr))
				{
					double dmax;
					pStatistics->get_Maximum(&dmax);
					double dmin;
					pStatistics->get_Minimum(&dmin);
					double stdev;
					pStatistics->get_StandardDeviation(&stdev);
				}

				IRasterStatistics2Ptr pStatistics2 = NULL;
				//pStatistics2->get_Covariances
			}
		}
	}

	return pRasterLayer;
}